﻿using System;
using System.Collections.Generic;
using MathematicallySafe.HeadCounter.Data;
using MathematicallySafe.HeadCounter.Data.Models;
using StructureMap;

namespace MathematicallySafe.HeadCounter.Services.Calculators
{
    public class CalculationService: ICalculationService
    {
        private static readonly IHeadCounterService HeadCounterService = ObjectFactory.GetInstance<IHeadCounterService>();
        private static readonly Guild Guild = HeadCounterService.Guild;

        void RaiderDataChanged(object sender, RaidersDataChangedEventArgs e)
        {
            Process(e.Raiders);
        }

        public void Process()
        {
            Process(HeadCounterService.Guild.ActiveRaiders);
        }

        public void Process(IEnumerable<Raider> raiders)
        {
            CalculateAttendance(raiders);
            CalculateLootMetrics(raiders);
            CalculateGearMetrics(raiders);
            CalculateDistanceFromMean(raiders);

            OnProcessed();
        }

        private void CalculateAttendance(IEnumerable<Raider> raiders)
        {
            var attendanceCalculator = new AttendanceCalculator(HeadCounterService.Options.ShortPeriodLength,
                                                                HeadCounterService.Options.LongPeriodLength);

            attendanceCalculator.Execute(raiders);
        }

        private void CalculateLootMetrics(IEnumerable<Raider> raiders)
        {
            var lootMetricCalculator = new LootMetricCalculator(HeadCounterService.Options.ShortPeriodLength,
                                                                HeadCounterService.Options.LongPeriodLength);

            lootMetricCalculator.Execute(raiders);

            Guild.ShortPeriodLootCountMean = lootMetricCalculator.ShortPeriodLootCountMean;
            Guild.ShortPeriodLootValueMean = lootMetricCalculator.ShortPeriodLootValueMean;
            Guild.ShortPeriodLootRateMean = lootMetricCalculator.ShortPeriodLootRateMean;
            Guild.ShortPeriodWeightedLootRateMean = lootMetricCalculator.ShortPeriodWeightedLootRateMean;
            Guild.ShortPeriodLootPriorityMean = lootMetricCalculator.ShortPeriodLootPriorityMean;

            Guild.LongPeriodLootCountMean = lootMetricCalculator.LongPeriodLootCountMean;
            Guild.LongPeriodLootValueMean = lootMetricCalculator.LongPeriodLootValueMean;
            Guild.LongPeriodLootRateMean = lootMetricCalculator.LongPeriodLootRateMean;
            Guild.LongPeriodWeightedLootRateMean = lootMetricCalculator.LongPeriodWeightedLootRateMean;
            Guild.LongPeriodLootPriorityMean = lootMetricCalculator.LongPeriodLootPriorityMean;

            Guild.LifetimeLootCountMean = lootMetricCalculator.LifetimeLootCountMean;
            Guild.LifetimeLootValueMean = lootMetricCalculator.LifetimeLootValueMean;
            Guild.LifetimeLootRateMean = lootMetricCalculator.LifetimeLootRateMean;
            Guild.LifetimeWeightedLootRateMean = lootMetricCalculator.LifetimeWeightedLootRateMean;
            Guild.LifetimeLootPriorityMean = lootMetricCalculator.LifetimeLootPriorityMean;
        }

        private void CalculateGearMetrics(IEnumerable<Raider> raiders)
        {
            var gearMetricCalculator = new GearMetricCalculator();
            gearMetricCalculator.Execute(raiders);
        }

        private void CalculateDistanceFromMean(IEnumerable<Raider> raiders)
        {
            var standardDeviationCalculator = new StandardDeviationCalculator();
            standardDeviationCalculator.Execute(raiders);
        }

        public event Action Processed;

        private void OnProcessed()
        {
            if (Processed != null)
            {
                Processed();
            }
        }
    }
}